/*
 * ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
 * Without permission, no one has the right to obtain, disclose or use this software in any way.
 */

package com.ecarx.systemui.plugin.controller.usb;


import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import android.os.StatFs;
import android.os.storage.StorageManager;

import com.ecarx.systemui.plugin.controller.base.BaseController;
import com.ecarx.systemui.plugin.model.listener.UsbStatusCallBack;
import com.ecarx.systemui.plugin.utils.AppUtils;
import com.ecarx.systemui.plugin.utils.LogUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class UsbController extends BaseController {

    private static final String TAG = "UsbControllerTag";

    public UsbController(Context context) {
        super(context);
    }

    @Override
    protected void initController(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        AppUtils.registerReceiver(context, this, filter);
    }

    private UsbStatusCallBack usbStatusCallBack;

    public void setUsbStatusCallBack(UsbStatusCallBack usbStatusCallBack) {
        this.usbStatusCallBack = usbStatusCallBack;
    }

    @SuppressWarnings({"unchecked", "ConstantConditions"})
    private boolean checkUsbHasMount(Context context) {
        StorageManager mStorageManager =
                (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        try {
            Method volumesM = getVolumesM();
            if (volumesM == null) {
                return false;
            }
            List<Object> vols = (List<Object>) volumesM.invoke(mStorageManager);
            if (vols == null) {
                return false;
            }
            Method diskM = getDiskM();
            Method isMountedReadableM = getMountedReadableM();
            Method isUsbM = getIsUsbM();
            if (diskM == null || isMountedReadableM == null || isUsbM == null) {
                return false;
            }
            for (Object volumeInfo : vols) {
                Object disk = diskM.invoke(volumeInfo);
                if (disk != null) {
                    boolean isOk = (boolean) isUsbM.invoke(disk);
                    if (isOk) {
                        return (boolean) isMountedReadableM.invoke(volumeInfo);
                    }
                }
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return false;
    }


    @SuppressWarnings("JavaReflectionMemberAccess")
    private Method getVolumesM() {
        Class<?> clazz;
        try {
            clazz = Class.forName("android.os.storage.StorageManager");
            return clazz.getMethod("getVolumes");
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    @SuppressLint("PrivateApi")
    private Method getIsUsbM() {
        Class<?> clazz;
        try {
            clazz = Class.forName("android.os.storage.DiskInfo");
            return clazz.getMethod("isUsb");
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    @SuppressLint("PrivateApi")
    private Method getDiskM() {
        Class<?> clazz;
        try {
            clazz = Class.forName("android.os.storage.VolumeInfo");
            return clazz.getMethod("getDisk");
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    @SuppressLint("PrivateApi")
    private Method getMountedReadableM() {
        Class<?> clazz;
        try {
            clazz = Class.forName("android.os.storage.VolumeInfo");
            return clazz.getMethod("isMountedReadable");
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        if (intent == null) {
            return;
        }
        String action = intent.getAction();
        LogUtils.d(TAG, "onReceive action:" + action);
        if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
            if (usbStatusCallBack != null) {
                usbStatusCallBack.onUsbAttached();
            }
        } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
            if (usbStatusCallBack != null) {
                usbStatusCallBack.onUsbDetached();
            }
        }

    }


    @Override
    public void destroyController(Context context) {
        context.unregisterReceiver(this);
    }

    // not work
    public void checkUsbOn(Context context) {
        boolean hasMount = checkUsbHasMount(context);
        LogUtils.d(TAG, "checkUsbHasMount hasMount:" + hasMount);
        if(hasMount){
            if (usbStatusCallBack != null) {
                usbStatusCallBack.onUsbAttached();
            }
        }else{
//            if (usbStatusCallBack != null) {
//                usbStatusCallBack.onUsbDetached();
//            }
        }
    }

    public boolean checkUDiskMounted(Context context) {
        StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        List<String> uDiskDeviceList = new ArrayList<>();
        try {
            Class storeManagerClazz = Class.forName("android.os.storage.StorageManager");

            Method getVolumesMethod = storeManagerClazz.getMethod("getVolumes");
            Class volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo");
            Method getFsUuidMethod = volumeInfoClazz.getMethod("getFsUuid");

            List<?> volumeInfos = (List<?>) getVolumesMethod.invoke(storageManager);

            if (volumeInfos == null) {
                return false;
            }
            for (Object volumeInfo : volumeInfos) {
                String uuid = (String) getFsUuidMethod.invoke(volumeInfo);
                if (uuid == null) {
                    continue;
                }
                uDiskDeviceList.add(uuid);
            }
            if (uDiskDeviceList.size() > 0) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
